package mgoDB

import (
	"bytes"
	"context"
	"strconv"
	"strings"
	"sync"
	"time"

	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

var (
	mapClient = sync.Map{}
	lock sync.Mutex // 连接锁定防止并发访问
)

//GetMgoClient 获取mongodb连接
func GetMgoClient(config map[string]string) (*mongo.Client, error) {
	var key strings.Builder
	key.WriteString(config["ipport"])
	key.WriteString("#")
	key.WriteString(config["dbname"])
	keyConn := key.String()
	client, ok := mapClient.Load(keyConn)
	if ok {
		return client.(*mongo.Client), nil
	}

	lock.Lock()
	defer lock.Unlock()

	/*二次获取防止并发多次连接*/
	client, ok = mapClient.Load(keyConn)
	if ok {
		return client.(*mongo.Client), nil
	}

	newClient, err := connect(config)
	if err != nil {
		return nil, err
	}
	mapClient.Store(keyConn, newClient)
	return newClient, nil
}

//connect 获取客户端
func connect(config map[string]string) (*mongo.Client, error) {
	//uri := "mongodb+srv://用户名:密码@官方给的.mongodb.net"
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	maxPoolSize := 200
	maxPoolSizeStr, ok := config["MaxPoolSize"]
	if ok {
		atoi, err := strconv.Atoi(maxPoolSizeStr)
		if err == nil {
			maxPoolSize = atoi
		}
	}

	var uri bytes.Buffer
	uri.WriteString("mongodb://")
	username, ok := config["username"]
	if !ok {
		username = ""
	}
	password, ok := config["password"]
	if !ok {
		password = ""
	}
	if username != "" {
		uri.WriteString(username)
		uri.WriteString(":")
		uri.WriteString(password)
		uri.WriteString("@")
	}
	uri.WriteString(config["ipport"])

	opts := options.Client().ApplyURI(uri.String()).SetMaxPoolSize(uint64(maxPoolSize))

	client, err := mongo.Connect(ctx, opts) // 连接池
	if err != nil {
		return nil, err
	}
	err = client.Ping(context.TODO(), nil)
	if err != nil {
		return nil, err
	}
	return client, nil
}
